package de.iritgo.skillfull.entity;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;

import de.iritgo.skillfull.component.visitor.DebugVisitor;
import de.iritgo.skillfull.component.visitor.SimpleDefaultMotionVisitor;

public class EntityManagerImpl implements EntityManager
{
	private Map<String, Entity> prototypeEntities;

	private Map<String, Entity> entities;

	private Map<String, LinkedList<Entity>> useableEntities;

	private List<Entity> removeEntityCache;

	private int nextId;

	public void setPrototypeEntities(Map<String, Entity> prototypeEntities)
	{
		this.prototypeEntities = prototypeEntities;
	}

	public void printAllEntities ()
	{
		for (Entity entity : prototypeEntities.values ())
		{
			System.out.println ("Entity: " + entity.getName ());
			entity.printAllEntityComponents ();
		}
	}

	public Entity getPrototypeEntity (String id)
	{
		
		if (useableEntities != null && useableEntities.get (id) != null)
		{
			if (useableEntities.get (id).size() > 0)
			{
				LinkedList<Entity> entityIdList = useableEntities.get (id);
				Entity entity = entityIdList.removeFirst();
				if (removeEntityCache == null || ! removeEntityCache.contains (entity))
				{
					entity.removed ();
					entity.init ();
					return entity;
				}
			}
		}
		Entity entity = prototypeEntities.get (id).cloneEntity();
		return entity;
	}
	
	public Entity cloneEntity ()
	{
		return null;
	}

	@Override
	public void addEntity (Entity entity)
	{
		if (entities == null)
			entities = new LinkedHashMap<String, Entity> ();
		entities.put (entity.getName (), entity);
	}

	@Override
	public Collection<Entity> getEntities ()
	{
		return entities.values ();
	}

	@Override
	public Entity getEntity (String id)
	{
		return entities.get (id);
	}

	@Override
	public void render (GameContainer container, Graphics g)
	{
		for (Entity entity : entities.values ())
		{
			entity.render (container, g);
		}
	}

	public void update (GameContainer container, int delta)
	{
		if (removeEntityCache != null)
		{
			for (Entity entity : removeEntityCache)
			{
				entity.removed ();
				entities.remove (entity.getName());
			}
			removeEntityCache.clear ();
		}
		for (Entity entity : entities.values ())
		{
			entity.update (container, delta);
		}
	}
	
	@Override
	public void removeEntity(Entity entity) 
	{
		// Bad!
		if (removeEntityCache == null)
		{
			removeEntityCache = new LinkedList<Entity> ();
		}
		removeEntityCache.add (entity);

		if (useableEntities == null)
		{
			useableEntities = new HashMap<String, LinkedList<Entity>> ();
		}
		LinkedList<Entity> useables = useableEntities.get (entity.getId ());
		if (useables  == null)
		{
			useables = new LinkedList<Entity> ();
			useableEntities.put (entity.getId (), useables);
		}
		useables.add (entity);
		removeEntityCache.add (entity);
	}
	
	public void createCache (String id, int size)
	{
		for (int i = 0; i < size ; ++i)
		{
			Entity entity = prototypeEntities.get (id).cloneEntity();
			if (useableEntities == null)
			{
				useableEntities = new HashMap<String, LinkedList<Entity>> ();
			}
			LinkedList<Entity> useables = useableEntities.get (entity.getId ());
			if (useables  == null)
			{
				useables = new LinkedList<Entity> ();
				useableEntities.put (entity.getId (), useables);
			}
			useables.add (entity);
		}
	}
	
	public int getNextId () 
	{
		return ++nextId;
	}
}
